home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 9 / CDACTUAL9.iso / share / Dos / VARIOS / pascal / ARCHIVES.SWG / 0001_Object Oriented Archive Viewers.pas
Encoding:
Pascal/Delphi Source File  |  1996-02-21  |  20.5 KB  |  831 lines

  1.  
  2. { OOAVTEST.PAS
  3.   cut out each of the units below and compile to test the use of this package}
  4.  
  5. uses      OOAV,Dos;
  6.  
  7. var       a:PArchive;
  8.           sr:SearchRec;
  9.           DT:DateTime;
  10.  
  11. begin
  12.   writeln('avail: ',memavail);
  13.  
  14.   { It's not necessary that you call IdentifyArchive,
  15.     but it's easy for checking when you've add new archive-types }
  16.   case IdentifyArchive(paramstr(1)) of
  17.     '?': writeln('Cannot open/identify current archive');
  18.     'Z': writeln('It''s a ZIP-archive');
  19.     'A': writeln('It''s an ARJ-archive');
  20.     'L': writeln('It''s an LZH-archive');
  21.     'C': writeln('It''s an ARC-archive');
  22.     'O': writeln('It''s a ZOO-archive');
  23.   end;
  24.  
  25.   a:=New(PArchive,Init);
  26.   if not a^.Name(paramstr(1)) then
  27.   begin
  28.     writeln('Cannot open file');
  29.     exit;
  30.   end;
  31.   writeln('Name':15,'Size':10,'Date':10,'Time':12);
  32.   a^.FindFirst(sr);
  33.   while sr.Name<>'' do
  34.   begin
  35.     write  (sr.Name:15,sr.Size:10);
  36.     UnpackTime(sr.Time,DT);
  37.     writeln(dt.day:10,dt.month:3,dt.year:5,dt.hour:4,dt.min:3,dt.sec:3);
  38.     a^.FindNext(sr);
  39.   end;
  40.   Dispose(A,Done);
  41.   writeln('End');
  42.   writeln('avail: ',memavail);
  43. end.
  44.  
  45. { the rest of the units follow }
  46. { CUT ----------------------------------------------------------- }
  47.  
  48. {
  49.         Object-Oriented Archive-viewer, version 3
  50.         ─────────────────────────────────────────
  51.         This Object-Oriented Archive-viewer (OOAV) is copyright (c) by
  52.         Edwin Groothuis, MavEtJu software. You are free to use it
  53.         if you agree with these three rules:
  54.  
  55.         1. You tell me you're using this unit.
  56.  
  57.         2. You give me proper credit in the documentation. (Like:
  58.            "This program uses the Object-Oriented Archive-viewer
  59.             (c) Edwin Groothuis, MavEtJu software".
  60.  
  61.         3. If you make Archive-objects for other archive-types, don't
  62.            hesitate to inform me so I can add them to the unit and
  63.            redistribute it!
  64.  
  65.         That's all!
  66.  
  67.         How to use this unit:
  68.         ─────────────────────
  69.         (see also the file ArchTest.pas)
  70.  
  71.         - Declare a variable Arch of the       var Arch:TArchive;
  72.           type TArchive                        begin
  73.         - Call it's constructor                  Arch.Init;
  74.         - Tell the unit which file you           if not Arch.Name('TEST.ZIP')
  75.           want to view. This function            then begin
  76.           returns a boolean. If this               writeln('TEST.ZIP is not
  77.           boolean is false, then the                        a valid archive');
  78.           file couldn't be identified              exit;
  79.           as a valid archive.                    end;
  80.         - Just like the dos-functions            Arch.FindFirst(sr);
  81.           FindFirst and FindNext, you            while sr.Name<>'' do
  82.           can search through the archive.        begin
  83.           The parameter you give with it           writeln(sr.Name);
  84.           is one of the SearchRec-type.            Arch.FindNext(sr);
  85.           If there are no more files in          end;
  86.           this archive, sr.Name will be
  87.           empty. Valid fields are
  88.           sr.Name, sr.Size and sr.Time
  89.         - Call the destructor                    Arch.Done;
  90.                                                end;
  91.  
  92.         - You can call the function
  93.           IdentifyArchive() to see what
  94.           kind of archive you're dealing
  95.           with.
  96.  
  97.         What if you want to add more archive-types
  98.         ──────────────────────────────────────────
  99.         - Add the unit name in the second Uses-statement.
  100.         - Find out how to identify it and add that algoritm
  101.           to the IdentifyArchive()-function. Please choose a
  102.           unique and no-nonsens character to return.
  103.         - Add it to the IdentifyArchive()-case in TArchive.Name.
  104.         - Create a FindFirst-method and FindNext-method for this
  105.           object.
  106.         - That's it! Simple, isn't it? (If it isn't, please see the
  107.           files ZipView, ArjView and others for examples ;-)
  108.  
  109.         Author:
  110.         ───────
  111.         Edwin Groothuis          email:
  112.         Johann Strausslaan 1     edwing@stack.urc.tue.nl (valid until 10-94)
  113.         5583ZA Aalst-Waalre      Edwin_Groothuis@p1.f205.n284.z2.gds.nl
  114.         The Netherlands          2:284/205.1@fidonet
  115.                                  115:3145/102.1@pascal-net
  116.  
  117.  
  118. }
  119.  
  120. unit      OOAV;
  121.  
  122. interface
  123.  
  124. uses      Dos;
  125.  
  126. {
  127.   General Archive, which is the father of all the specific archives. See
  128.   OOAVZip, OOAVArj and others for examples.
  129. }
  130. type      PGeneralArchive=^TGeneralArchive;
  131.           TGeneralArchive=object
  132.                             _FArchive:file;
  133.  
  134.                             constructor Init;
  135.                             destructor Done;virtual;
  136.  
  137.                             procedure FindFirst(var sr:SearchRec);virtual;
  138.                             procedure FindNext(var sr:SearchRec);virtual;
  139.                           end;
  140.  
  141. {
  142.   TArchive is the object you're working with. See the documentation at the
  143.   begin of this file for more information
  144. }
  145. type      PArchive=^TArchive;
  146.           TArchive=object
  147.                      constructor Init;
  148.                      destructor Done;
  149.  
  150.                      function  Name(const n:string):boolean;
  151.  
  152.                      procedure FindFirst(var sr:SearchRec);
  153.                      procedure FindNext(var sr:SearchRec);
  154.  
  155.                    private
  156.                      _Name:string;
  157.                      _Archive:PGeneralArchive;
  158.                    end;
  159.  
  160.  
  161. function  IdentifyArchive(const Name:string):char;
  162.  
  163. implementation
  164.  
  165. uses      Objects,Strings,
  166.           OOAVZip,OOAVArj,OOAVLzh,OOAVArc,OOAVZoo;
  167.  
  168.  
  169. function  IdentifyArchive(const Name:string):char;
  170. {
  171.   returns:
  172.     '?': unknown archive
  173.     'A': Arj-archive;
  174.     'Z': Zip-archive
  175.     'L': Lzh-archive
  176.     'C': Arc-archive
  177.     'O': Zoo-archive
  178. }
  179. var       f:file;
  180.           a:array[0..10] of char;
  181.           bc:word;
  182.           s:string;
  183.           OldFileMode:byte;
  184. begin
  185.   if Name='' then
  186.   begin
  187.     IdentifyArchive:='?';
  188.     exit;
  189.   end;
  190.  
  191.   OldFileMode:=FileMode;
  192.   FileMode:=0;
  193.   assign(f,Name);
  194.   {$I-}reset(f,1);{$I+}
  195.   FileMode:=OldFileMode;
  196.   if IOresult<>0 then
  197.   begin
  198.     IdentifyArchive:='?';
  199.     exit;
  200.   end;
  201.  
  202.   blockread(f,a,sizeof(a),bc);
  203.   close(f);
  204.   if bc=0 then
  205.   begin
  206.     IdentifyArchive:='?';
  207.     exit;
  208.   end;
  209.  
  210.   if (a[0]=#$60) and (a[1]=#$EA) then
  211.   begin
  212.     IdentifyArchive:='A';  { ARJ }
  213.     exit;
  214.   end;
  215.  
  216.   if (a[0]='P') and (a[1]='K') then
  217.   begin
  218.     IdentifyArchive:='Z';  { ZIP }
  219.     exit;
  220.   end;
  221.  
  222.   if a[0]=#$1A then
  223.   begin
  224.     IdentifyArchive:='C';  { ARC }
  225.     exit;
  226.   end;
  227.  
  228.   if (a[0]='Z') and (a[1]='O') and (a[2]='O') then
  229.   begin
  230.     IdentifyArchive:='O';  { ZOO }
  231.     exit;
  232.   end;
  233.  
  234.   s:=Name;
  235.   for bc:=1 to length(s) do
  236.     s[bc]:=upcase(s[bc]);
  237.   if copy(s,pos('.',s),4)='.LZH' then
  238.   begin
  239.     IdentifyArchive:='L';  { LZH }
  240.     exit;
  241.   end;
  242.  
  243.   IdentifyArchive:='?';
  244. end;
  245.  
  246.  
  247. constructor TGeneralArchive.Init;
  248. begin
  249.   Abstract;
  250. end;
  251.  
  252.  
  253. destructor TGeneralArchive.Done;
  254. begin
  255. end;
  256.  
  257.  
  258. procedure TGeneralArchive.FindFirst(var sr:SearchRec);
  259. begin
  260.   Abstract;
  261. end;
  262.  
  263.  
  264. procedure TGeneralArchive.FindNext(var sr:SearchRec);
  265. begin
  266.   Abstract;
  267. end;
  268.  
  269.  
  270. constructor TArchive.Init;
  271. begin
  272.   _Name:='';
  273.   _Archive:=nil;
  274. end;
  275.  
  276.  
  277. destructor TArchive.Done;
  278. begin
  279.   if _Archive<>nil then
  280.   begin
  281.     close(_Archive^._FArchive);
  282.     Dispose(_Archive,Done);
  283.   end;
  284. end;
  285.  
  286.  
  287. function  TArchive.Name(const n:string):boolean;
  288. var       sr:SearchRec;
  289.           OldFileMode:byte;
  290. begin
  291.   if _Archive<>nil then
  292.   begin
  293.     close(_Archive^._FArchive);
  294.     Dispose(_Archive,Done);
  295.     _Archive:=nil;
  296.   end;
  297.  
  298.   Name:=false;
  299.   _Name:=n;
  300.   Dos.FindFirst(_Name,anyfile,sr);
  301.   if DosError<>0 then
  302.     exit;
  303.  
  304.   case IdentifyArchive(_Name) of
  305.     '?': exit;
  306.     'A': _Archive:=New(PArjArchive,Init);
  307.     'Z': _Archive:=New(PZipArchive,Init);
  308.     'L': _Archive:=New(PLzhArchive,Init);
  309.     'C': _Archive:=New(PArcArchive,Init);
  310.     'O': _Archive:=New(PZooArchive,Init);
  311.   end;
  312.  
  313.   OldFileMode:=FileMode;
  314.   FileMode:=0;
  315.   Assign(_Archive^._FArchive,n);
  316.   {$I-}reset(_Archive^._FArchive,1);{$I+}
  317.   FileMode:=OldFileMode;
  318.   if IOresult<>0 then
  319.   begin
  320.     Dispose(_Archive);
  321.     exit;
  322.   end;
  323.  
  324.   Name:=true;
  325. end;
  326.  
  327.  
  328. procedure TArchive.FindFirst(var sr:SearchRec);
  329. begin
  330.   FillChar(sr,sizeof(sr),0);
  331.   if _Archive=nil then
  332.     exit;
  333.   _Archive^.FindFirst(sr);
  334. end;
  335.  
  336. procedure TArchive.FindNext(var sr:SearchRec);
  337. begin
  338.   FillChar(sr,sizeof(sr),0);
  339.   if _Archive=nil then
  340.     exit;
  341.   _Archive^.FindNext(sr);
  342. end;
  343.  
  344. end.
  345. { CUT ----------------------------------------------------------- }
  346. {
  347.         Object-Oriented Archive-viewer: ARC-part
  348. }
  349.  
  350. unit OOAVArc;
  351.  
  352. interface
  353.  
  354. uses      Dos,OOAV;
  355.  
  356. Type      AFHeader = Record
  357.                  HeadId  : byte;
  358.                  DataType : byte;   { 0 = no more data }
  359.                  Name     : array[0..12] of char;
  360.                  CompSize : longint;
  361.                  FileDate : word;
  362.                  FileTime : word;
  363.                  Crc      : word;
  364.                  OrigSize : longint;
  365.                end;
  366.  
  367.  
  368. type      PArcArchive=^TArcArchive;
  369.           TArcArchive=object(TGeneralArchive)
  370.                         constructor Init;
  371.                         procedure FindFirst(var sr:SearchRec);virtual;
  372.                         procedure FindNext(var sr:SearchRec);virtual;
  373.                       private
  374.                         _FHdr:AFHeader;
  375.                         _SL:longint;
  376.                         procedure GetHeader(var sr:SearchRec);
  377.                       end;
  378.  
  379. implementation
  380.  
  381. const     BSize=4096;
  382. var       BUFF:array[1..BSize] of Byte;
  383.  
  384.  
  385.  
  386. constructor TArcArchive.Init;
  387. begin
  388.   FillChar(_FHdr,sizeof(_FHdr),0);
  389. end;
  390.  
  391.  
  392. procedure TArcArchive.GetHeader(var sr:SearchRec);
  393. var       bc:word;
  394.           b:byte;
  395. begin
  396.   FillChar(_FHdr,SizeOf(_FHdr),#0);
  397.   FillChar(BUFF,BSize,#0);
  398.   Seek(_FArchive,_SL);
  399.   BlockRead(_FArchive,BUFF,BSIZE,bc);
  400.   Move(BUFF[1],_FHdr,SizeOf(_FHdr));
  401.   with _FHdr do
  402.   begin
  403.     if DataType<>0 then
  404.     begin
  405.       b:=0;sr.Name:='';
  406.       while Name[b]<>#0 do
  407.       begin
  408.         if Name[b]='/' then
  409.           sr.Name:=''
  410.         else
  411.           sr.Name:=sr.Name+Name[b];
  412.         inc(b);
  413.       end;
  414.       sr.Size:=OrigSize;
  415.       if DataType=0 then sr.Size:=0;
  416.       sr.Time:=FileDate*longint(256*256)+FileTime;
  417.       inc(_SL,CompSize);
  418.       inc(_SL,sizeof(_FHDR));
  419.     end;
  420.   end;
  421. end;
  422.  
  423.  
  424. Procedure TArcArchive.FindFirst(var sr:SearchRec);
  425. begin
  426.  _SL:=0;
  427.  GetHeader(sr);
  428. end;
  429.  
  430.  
  431. procedure TArcArchive.FindNext(var sr:SearchRec);
  432. begin
  433.  GetHeader(sr);
  434. end;
  435.  
  436.  
  437. end.
  438. { CUT ----------------------------------------------------------- }
  439. {
  440.         Object-Oriented Archive-viewer: ARJ-part
  441. }
  442.  
  443. unit OOAVArj;
  444.  
  445. interface
  446.  
  447. uses      Dos,OOAV;
  448.  
  449. Type      AFHeader = Record
  450.                        HeadId  : Word;                         { 60000 }
  451.                        BHdrSz  : Word;             { Basic Header Size }
  452.                        FHdrSz  : Byte;              { File Header Size }
  453.                        AVNo    : Byte;
  454.                        MAVX    : Byte;
  455.                        HostOS  : Byte;
  456.                        Flags   : Byte;
  457.                        SVer    : Byte;
  458.                        FType   : Byte;    { must be 2 for basic header }
  459.                        Res1    : Byte;
  460.                        DOS_DT  : LongInt;
  461.                        CSize   : LongInt;            { Compressed Size }
  462.                        OSize   : LongInt;            { Original Size }
  463.                        SEFP    : LongInt;
  464.                        FSFPos  : Word;
  465.                        SEDLgn  : Word;
  466.                        Res2    : Word;
  467.                        NameDat : array[1..120] of char;{ start of Name, etc. }
  468.                        Res3    : array[1..10] of char;
  469.                      end;
  470.  
  471.  
  472. type      PArjArchive=^TArjArchive;
  473.           TArjArchive=object(TGeneralArchive)
  474.                         constructor Init;
  475.                         procedure FindFirst(var sr:SearchRec);virtual;
  476.                         procedure FindNext(var sr:SearchRec);virtual;
  477.                       private
  478.                         _FHdr:AFHeader;
  479.                         _SL:longint;
  480.                         procedure GetHeader(var sr:SearchRec);
  481.                       end;
  482.  
  483. implementation
  484.  
  485. const     BSize=4096;
  486. var       BUFF:array[1..BSize] of Byte;
  487.  
  488.  
  489.  
  490. constructor TArjArchive.Init;
  491. begin
  492.   FillChar(_FHdr,sizeof(_FHdr),0);
  493. end;
  494.  
  495.  
  496. procedure TArjArchive.GetHeader(var sr:SearchRec);
  497. var       bc:word;
  498.           b:byte;
  499. begin
  500.   FillChar(_FHdr,SizeOf(_FHdr),#0);
  501.   FillChar(BUFF,BSize,#0);
  502.   Seek(_FArchive,_SL);
  503.   BlockRead(_FArchive,BUFF,BSIZE,bc);
  504.   Move(BUFF[1],_FHdr,SizeOf(_FHdr));
  505.   with _FHdr do
  506.   begin
  507.     if BHdrSz>0 then
  508.     begin
  509.       b:=1;sr.Name:='';
  510.       while NameDat[b]<>#0 do
  511.       begin
  512.         if NameDat[b]='/' then
  513.           sr.Name:=''
  514.         else
  515.           sr.Name:=sr.Name+NameDat[b];
  516.         inc(b);
  517.       end;
  518.       sr.Size:=BHdrSz+CSize;
  519.       if FType=2 then sr.Size:=BHdrSz;
  520.       if BHdrSz=0 then sr.Size:=0;
  521.       inc(_SL,sr.Size+10);
  522.       sr.Time:=DOS_DT;
  523.     end;
  524.   end;
  525. end;
  526.  
  527.  
  528. Procedure TArjArchive.FindFirst(var sr:SearchRec);
  529. begin
  530.   _SL:=0;
  531.   GetHeader(sr);
  532.   GetHeader(sr);
  533. { Why a call to GetHeader() twice?
  534.   Because ARJ stores the name of the archive in the first field }
  535. end;
  536.  
  537.  
  538. procedure TArjArchive.FindNext(var sr:SearchRec);
  539. begin
  540.   GetHeader(sr);
  541. end;
  542.  
  543.  
  544. end.
  545. { CUT ----------------------------------------------------------- }
  546. {
  547.         Object-Oriented Archive-viewer: LZH-part
  548. }
  549.  
  550. Unit      OOAVLzh;
  551.  
  552. Interface
  553.  
  554. Uses      Dos,OOAV;
  555.  
  556. Type      LFHeader=Record
  557.                      Headsize,Headchk          :byte;
  558.                      HeadID                    :packed Array[1..5] of char;
  559.                      Packsize,Origsize,Filetime:longint;
  560.                      Attr                      :word;
  561.                      Filename                  :string[12];
  562.                      f32                       :pathstr;
  563.                      dt                        :DateTime;
  564.                    end;
  565.  
  566.  
  567. type      PLzhArchive=^TLzhArchive;
  568.           TLzhArchive=object(TGeneralArchive)
  569.                         constructor Init;
  570.                         procedure FindFirst(var sr:SearchRec);virtual;
  571.                         procedure FindNext(var sr:SearchRec);virtual;
  572.                       private
  573.                         _FHdr:LFHeader;
  574.                         _SL:longint;
  575.                         procedure GetHeader(var sr:SearchRec);
  576.                       end;
  577.  
  578.  
  579. Implementation
  580.  
  581.  
  582. constructor TLzhArchive.Init;
  583. begin
  584.   _SL:=0;
  585.   FillChar(_FHdr,sizeof(_FHdr),0);
  586. end;
  587.  
  588.  
  589. procedure TLzhArchive.GetHeader(var sr:SearchRec);
  590. var       nr:word;
  591. begin
  592.   fillchar(sr,sizeof(sr),0);
  593.   seek(_FArchive,_SL);
  594.   if eof(_FArchive) then
  595.     exit;
  596.   blockread(_FArchive,_FHdr,sizeof(LFHeader),nr);
  597.   if _FHdr.headsize=0 then
  598.     exit;
  599.   inc(_SL,_FHdr.headsize);
  600.   inc(_SL,2);
  601.   inc(_SL,_FHdr.packsize);
  602.   if _FHdr.headsize<>0 then
  603.     UnPackTime(_FHdr.FileTime,_FHdr.DT);
  604.   sr.Name:=_FHdr.FileName;
  605.   sr.Size:=_FHdr.OrigSize;
  606.   sr.Time:=_FHdr.FileTime;
  607. end;
  608.  
  609.  
  610. procedure TLzhArchive.FindFirst(var sr:SearchRec);
  611. begin
  612.   _SL:=0;
  613.   GetHeader(sr);
  614. end;
  615.  
  616.  
  617. procedure TLzhArchive.FindNext(var sr:SearchRec);
  618. begin
  619.   GetHeader(sr);
  620. end;
  621.  
  622.  
  623. end.
  624.  
  625. { CUT ----------------------------------------------------------- }
  626. {
  627.         Object-Oriented Archive-viewer: ZIP-part
  628. }
  629.  
  630. Unit      OOAVZip;
  631.  
  632. Interface
  633.  
  634. Uses      Dos,OOAV;
  635.  
  636.  
  637. Type      ZFHeader=Record
  638.                      Signature                         :longint;
  639.                      Version,GPBFlag,Compress,Date,Time:word;
  640.                      CRC32,CSize,USize                 :longint;
  641.                      FNameLen,ExtraField               :word;
  642.                    end;
  643.  
  644.  
  645. type      PZipArchive=^TZipArchive;
  646.           TZipArchive=object(TGeneralArchive)
  647.                         constructor Init;
  648.                         procedure FindFirst(var sr:SearchRec);virtual;
  649.                         procedure FindNext(var sr:SearchRec);virtual;
  650.                       private
  651.                         Hdr:ZFHeader;
  652.                         procedure GetHeader(var sr:SearchRec);
  653.                       end;
  654.  
  655. implementation
  656.  
  657.  
  658. Const     SIG = $04034B50;                  { Signature }
  659.  
  660.  
  661. constructor TZipArchive.Init;
  662. begin
  663.   FillChar(Hdr,sizeof(Hdr),0);
  664. end;
  665.  
  666.  
  667. procedure TZipArchive.GetHeader(var sr:SearchRec);
  668. var       b:byte;
  669.           bc:word;
  670. begin
  671.   fillchar(sr,sizeof(sr),0);
  672.   if eof(_FArchive) then
  673.     exit;
  674.   BlockRead(_FArchive,Hdr,SizeOf(Hdr),bc);
  675.   if bc<>Sizeof(Hdr) then
  676.     exit;
  677. { Why checking for Hdr.FNamelen=0?
  678.   Because the comments inserted in a ZIP-file are at the last field }
  679.   if Hdr.FNameLen=0 then
  680.     exit;
  681.   sr.Name:='';
  682.   Repeat
  683.     BlockRead(_FArchive,b,1);
  684.     If b<>0 Then
  685.       sr.Name:=sr.Name+Chr(b);
  686.   Until (length(sr.Name)=Hdr.FNameLen) or (b=0);
  687.   if b=0 then
  688.     exit;
  689.   Seek(_FArchive,FilePos(_FArchive)+Hdr.CSize+Hdr.ExtraField);
  690.   sr.Size:=Hdr.USize;
  691.   sr.Time:=Hdr.Date+Hdr.Time*longint(256*256);
  692. end;
  693.  
  694.  
  695. Procedure TZipArchive.FindFirst(var sr:SearchRec);
  696. begin
  697.   GetHeader(sr);
  698. end;
  699.  
  700.  
  701. Procedure TZipArchive.FindNext(var sr:SearchRec);
  702. begin
  703.   GetHeader(sr);
  704. end;
  705.  
  706.  
  707. end.
  708.  
  709. { CUT ----------------------------------------------------------- }
  710. {
  711.         Object-Oriented Archive-viewer: ZOO-part
  712. }
  713.  
  714. unit OOAVZoo;
  715.  
  716. interface
  717.  
  718. uses      Dos,OOAV;
  719.  
  720. const     SIZ_TEXT=20;
  721. const     FNAMESIZE=13;
  722. const     MAX_PACK=1;
  723. const     LO_TAG=$a7dc;
  724. const     HI_TAG=$fdc4;
  725.  
  726.  
  727. type      ZFHeader=record
  728.                      lo_tag:word;
  729.                      hi_tag:word;
  730.                      _type:byte;
  731.                      packing_method:byte;
  732.                      next:longint;      { pos'n of next directory entry }
  733.                      offset:longint;
  734.                      date:word;         { DOS format date }
  735.                      time:word;         { DOS format time }
  736.                      file_crc:word;     { CRC of this file }
  737.                      org_size:longint;
  738.                      size_now:longint;
  739.                      major_ver:byte;
  740.                      minor_ver:byte;
  741.                      deleted:boolean;
  742.                      comment:longint;   { points to comment;  zero if none }
  743.                      cmt_size:word;     { length of comment, 0 if none }
  744.                      unknown:byte;
  745.                      fname:array[0..FNAMESIZE-1] of char;
  746.                    end;
  747.  
  748. type      PZooArchive=^TZooArchive;
  749.           TZooArchive=object(TGeneralArchive)
  750.                         constructor Init;
  751.                         procedure FindFirst(var sr:SearchRec);virtual;
  752.                         procedure FindNext(var sr:SearchRec);virtual;
  753.                       private
  754.                         _FHdr:ZFHeader;
  755.                         procedure GetHeader;
  756.                         procedure GetEntry(var sr:SearchRec);
  757.                       end;
  758.  
  759. implementation
  760.  
  761.  
  762.  
  763. type      zooHeader=record
  764.                       text:array[0..SIZ_TEXT-1] of char;
  765.                       lo_tag:word;
  766.                       hi_tag:word;
  767.                       start:longint;
  768.                       minus:longint;
  769.                       major_ver:char;
  770.                       minor_ver:char;
  771.                     end;
  772.  
  773.  
  774. constructor TZooArchive.Init;
  775. begin
  776.   FillChar(_FHdr,sizeof(_FHdr),0);
  777. end;
  778.  
  779.  
  780. procedure TZooArchive.GetHeader;
  781. var       hdr:zooHeader;
  782.           bc:word;
  783. begin
  784.   seek(_FArchive,0);
  785.   BlockRead(_FArchive,hdr,sizeof(hdr),bc);
  786.   seek(_FArchive,hdr.start);
  787. end;
  788.  
  789.  
  790. procedure TZooArchive.GetEntry(var sr:SearchRec);
  791. var       bc:word;
  792.           b:byte;
  793. begin
  794.   FillChar(_FHdr,SizeOf(_FHdr),#0);
  795.   BlockRead(_FArchive,_FHdr,sizeof(_FHdr),bc);
  796.   with _FHdr do
  797.   begin
  798.     if _Type<>0 then
  799.     begin
  800.       b:=0;sr.Name:='';
  801.       while FName[b]<>#0 do
  802.       begin
  803.         if FName[b]='/' then
  804.           sr.Name:=''
  805.         else
  806.           sr.Name:=sr.Name+FName[b];
  807.         inc(b);
  808.       end;
  809.       sr.Size:=Org_Size;
  810.       if _Type=0 then sr.Size:=0;
  811.       sr.Time:=Date*longint(256*256)+Time;
  812.       Seek(_FArchive,_FHdr.next);
  813.     end;
  814.   end;
  815. end;
  816.  
  817.  
  818. procedure TZooArchive.FindFirst(var sr:SearchRec);
  819. begin
  820.  GetHeader;
  821.  GetEntry(sr);
  822. end;
  823.  
  824.  
  825. procedure TZooArchive.FindNext(var sr:SearchRec);
  826. begin
  827.  GetEntry(sr);
  828. end;
  829.  
  830.  
  831. end.